#pragma once
#include "CentralCache.h"
#include "PageCache.h"
CentralCache CentralCache::_sInst;
span* CentralCache::Getonespan(spanlist& list, size_t size)
{
	span* cur = list.begin();//先查看当前的spanlist中是否有非空的span，
	while (cur != list.end())
	{ 
		if (cur->_freelist) {
			return cur;
		}
		cur = cur->_next;
	}
	list._mtx.unlock();//先把centralcache的桶锁解开，以便于有的进程释放内存

	PageCache::GetInstance()->_pagemtx.lock();
	span* s1=PageCache::GetInstance()->newspan(Sizemodify::sizemovepage(size));	//走到这里说明没有非空的span只能向pagecache要
	s1->_isused = true;
	s1->_objsize = size;
	PageCache::GetInstance()->_pagemtx.unlock();

	//对获取的span进行切分,此时并不需要加锁，因为这时其他线程访问不到这个span
	char* start = (char*)(s1->_pageid << page_shift);//内存页的起始地址
	char* end = start + ((s1->_n) << page_shift);
	char* tmp= (char*)(s1->_pageid << page_shift);
	s1->_freelist= start;
	start += size;
	void* tail = s1->_freelist;
	while (start < end)
	{
		*((void**)tail) = (void*)start;
		tail = start;
		start += size;
	}
	*((void**)tail) = nullptr;//tail的下一个应该为nullptr

	// 1、条件断点
	 //2、疑似死循环，可以中断程序，程序会在正在运行的地方停下来
	//int j = 0;
	//void* pcur = s1->_freelist;
	//while (pcur)
	//{
	//	pcur = (*(void**)pcur);
	//	++j;
	//}

	//if (j != ((s1->_n<<page_shift) / size))
	//{
	//	int x = 0;
	//}

	//切好span之后需要将span挂到桶上，需要再次上锁
	list._mtx.lock();
	list.pushfront(s1);
	return s1;
}

//这里的start和end是闭区间，也就是内存也包括start和end
size_t CentralCache::FetchRangobj(void*& start, void*& end, size_t batchNum, size_t size,size_t index)//从中心缓存获取一定数量的对象给thread cache
{
	_centralspanlistarray[index]._mtx.lock();//上锁
	span* s1 = CentralCache::Getonespan(_centralspanlistarray[index], size);
	assert(s1);
	assert(s1->_freelist);
	size_t actualnum = 1;
	start = s1->_freelist; 
	end = start;
	int i = 0;
	for (; i < batchNum - 1 && *((void**)end); i++)
	{
		end = *((void**)end);
		actualnum++;
	}
	s1->_freelist = *((void**)end);
	*((void**)end) = nullptr;
	s1->_usedcount += actualnum;
	//条件断点
	//int j = 0;
	//void* cur = start;
	//while (cur)
	//{
	//	cur = (*(void**)cur);
	//	j++;
	//}
	//if (j != actualnum)
	//{
	//	int x = 0;
	//}
	//
	_centralspanlistarray[index]._mtx.unlock();//上锁
	return actualnum;
}
void CentralCache::realse_to_central_span(void* start, size_t size)
{
	size_t index = Sizemodify::Index(size);
	_centralspanlistarray[index]._mtx.lock();
	span* sp = nullptr;
	void* next = nullptr;
	while (start)
	{
		next = *((void**)start);
		sp = PageCache::GetInstance()->map_obj_to_span(start);
		*((void**)start) = sp->_freelist;
		sp->_freelist = start;
		sp->_usedcount--;
		if (sp->_usedcount == 0)//span切分出去的的所有小块都回来了，该span就可以还给pagecache
		{
			if (sp->_next == nullptr)
				int f = 0;
			_centralspanlistarray[index].Erase(sp);
			sp->_isused = false;
			sp->_freelist = nullptr;
			////////////////////////////////////////

			_centralspanlistarray[index]._mtx.unlock();

			PageCache::GetInstance()->_pagemtx.lock();
			PageCache::GetInstance()->Realse_span_to_page(sp);
			PageCache::GetInstance()->_pagemtx.unlock();

			_centralspanlistarray[index]._mtx.lock();
		}
		start = next;
	}
	_centralspanlistarray[index]._mtx.unlock();
}
